﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO; //文件处理
using System.Threading; //创建多线程使用
using System.IO.Ports; //查看电脑端口
using System.Text.RegularExpressions;

namespace Mosdar_Weld
{
    public partial class Form1 : Form
    {
        BarCodeHook BarCode = new BarCodeHook();

        List<byte> bytList = new List<byte>();

        private bool _loadUpdateFileStatus = false; //加载升级文件状态 (true,加载成功 / false,未加载)
        private bool _BarCodeStatus = false;

        public Form1()
        {
            InitializeComponent();
            BarCode.BarCodeEvent += new BarCodeHook.BardCodeDeletegate(BarCode_BarCodeEvent);
            ComboxSelectIndexInit();
            ScanAvailableSerialPort();
        }

        private void ComboxSelectIndexInit()
        {
            this.comboBox4.SelectedIndex = 3;
            this.comboBox7.SelectedIndex = 1;
            this.comboBox8.SelectedIndex = 0;
            this.comboBox9.SelectedIndex = 0;
            this.comboBox5.SelectedIndex = 1;
        }

        private delegate void ShowInfoDelegate(object sender, BarCodesEventArgs barCode);
        private void ShowInfo(object sender, BarCodesEventArgs barCode)
        {
            if (this.InvokeRequired)
            {
                BeginInvoke(new ShowInfoDelegate(ShowInfo), new object[] { sender, barCode });
            }
            //else
            //{
            //    this.textBox1.Clear();
            //    this.textBox1.Focus();
            //    //this.textBox1.Text = "";
            //}

        }

        #region 串口处理
        //扫描可用串口
        private void button_UartPortScan_Click(object sender, EventArgs e)
        {
            ScanAvailableSerialPort();
        }

        /// <summary>
        /// 获取当前所有串口信息
        /// </summary>
        private void ScanAvailableSerialPort()
        {
            SerialTransmission Serial = new SerialTransmission();
            string currentPort = comboBox6.Text; //保存当前选择的串口号
            Serial.GetSerialPort(comboBox6);
            comboBox6.Text = currentPort;
        }

        //将串口号全名提取处COM口号
        private string GetUartComNumber(string UartPortWholeName)
        {
            try
            {
                string[] sArray = UartPortWholeName.Split(new string[] { "(", ")" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string e in sArray)
                {
                    if (e.Contains("COM")) return e;
                }
            }
            catch { }

            return "";
        }

        //获取串口号名 (如COM1)
        private string GetSerialPortName(string portText)
        {
            Regex reg = new Regex(@"COM\d+");
            Match matchs = reg.Match(portText);
            if (matchs != null && matchs.Groups[0].ToString() != string.Empty)
            {
                Debugging.output("port_name = " + matchs.Groups[0].ToString());
                return matchs.Groups[0].ToString();
            }
            else
            {
                Debugging.output("无法识别的串口。");
            }

            return "";
        }
        #endregion

        #region 升级固件合并
        private void button1_Click(object sender, EventArgs e)
        {
            openFile(txtboxDispPath1, textBox3);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            openFile(txtboxDispPath2, textBox4);
        }

        private void button6_Click(object sender, EventArgs e)
        {
            openFile(txtboxDispPath3, textBox6);
        }

        private void openFile(TextBox txtbox1, TextBox txtbox2)
        {
            openFileDialog1.Title = "选择需要拼接的固件";

            openFileDialog1.InitialDirectory = Application.StartupPath;
            openFileDialog1.Filter = "Bin file(*.bin)|*.bin";
            openFileDialog1.RestoreDirectory = true;
            //string Mytext = "";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                FileInfo f = new FileInfo(openFileDialog1.FileName); //创建FileInfo对象
                txtbox1.Text = openFileDialog1.FileName;
                txtbox2.Text = f.Length.ToString() + " Byte";
            }
        }

        private void button7_Click(object sender, EventArgs e)
        {
            saveFileDialog1.Title = "保存bin文件";
            saveFileDialog1.InitialDirectory = Application.StartupPath;
            saveFileDialog1.Filter = "Bin file(*.bin)|*.bin";
            saveFileDialog1.RestoreDirectory = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                FileInfo f = new FileInfo(saveFileDialog1.FileName); //创建FileInfo对象
                combinBinFiles();
                createCombinBinFile(saveFileDialog1.FileName);
                textBox8.Text = f.Length.ToString() + " Byte";
                _loadUpdateFileStatus = true;
            }
        }

        private void button8_Click(object sender, EventArgs e)
        {
            openFile(txtSaveBinFilePath, textBox8);
            _loadUpdateFileStatus = true;
        }

        void createCombinBinFile(string fileName)
        {
            FileStream binFile = new FileStream(fileName, FileMode.Create);

            BinaryWriter binWriter = new BinaryWriter(binFile);

            byte[] byteTemp = new byte[bytList.Count];
            bytList.CopyTo(byteTemp, 0);
            binWriter.Write(byteTemp, 0, byteTemp.Length);
            binWriter.Close();
            txtSaveBinFilePath.Text = fileName;
            bytList.Clear();
        }



        private void combinBinFiles()
        {
            try
            {
                byte[] binDataTemp1 = readBinFiles(txtboxDispPath1.Text);
                byte[] binPackLen1 = new byte[2];
                binPackLen1[0] = (byte)(binDataTemp1.Length / 256);
                binPackLen1[1] = (byte)(binDataTemp1.Length);
                bytList.AddRange(binPackLen1);
                bytList.AddRange(binDataTemp1);

                byte[] binDataTemp2 = readBinFiles(txtboxDispPath2.Text);
                byte[] binPackLen2 = new byte[2];
                binPackLen2[0] = (byte)(binDataTemp2.Length / 256);
                binPackLen2[1] = (byte)(binDataTemp2.Length);
                bytList.AddRange(binPackLen2);
                bytList.AddRange(binDataTemp2);

                byte[] binDataTemp3 = readBinFiles(txtboxDispPath3.Text);
                byte[] binPackLen3 = new byte[2];
                binPackLen3[0] = (byte)(binDataTemp3.Length / 256);
                binPackLen3[1] = (byte)(binDataTemp3.Length);
                bytList.AddRange(binPackLen3);
                bytList.AddRange(binDataTemp3);

            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            finally
            {
                MessageBox.Show("拼接成功");
            }
        }

        private byte[] readBinFiles(string binFilePath)
        {
            int file_len;
            int read_len;
            string Mytext = "";

            string filePath1 = binFilePath;


            FileStream binFile = new FileStream(filePath1, FileMode.Open);
            BinaryReader binReader = new BinaryReader(binFile);
            file_len = (int)binFile.Length;
            byte[] binchar = new byte[] { };
            while (file_len > 0)
            {
                if (file_len / 256 > 0)
                {
                    read_len = 256;
                }
                else
                {
                    read_len = file_len % 256;
                }
                binchar = binReader.ReadBytes(read_len);
                foreach (byte j in binchar)
                {
                    Mytext += j.ToString("X2");
                    Mytext += " ";
                }
                file_len -= read_len;
            }
            Mytext = Mytext.Trim();
            string[] strArray = Mytext.Split(' ');
            byte[] binDataArray = new byte[strArray.Length];
            for (int i = 0; i < strArray.Length; i++)
            {
                binDataArray[i] = Convert.ToByte(strArray[i], 16);
            }
            binReader.Close();
            return binDataArray;

            //foreach (var s in strArray)
            //{
            //    //将十六进制的字符串转换成数值
            //    bytList.Add(Convert.ToByte(s, 16));
            //}

            //FramLen = bytList.Count;
            //sendTimes = FramLen / 1024 + (FramLen % 1024 != 0 ? 1 : 0);
            //MessageBox.Show("导入成功，数据包大小为" + FramLen +
            //    "bytes", "固件信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //btnWriteBin.Enabled = true;
        }
        #endregion

        #region 升级文件数据提取

        //private void Button1_OpenUpdateFile_Click(object sender, EventArgs e)
        //{
        //    //创建打开文件对话框对象
        //    OpenFileDialog ofd = new OpenFileDialog();
        //    ofd.Filter = "|*.bin"; //只查看bin格式文件
        //    if (ofd.ShowDialog() == DialogResult.OK)//判断是选中文件
        //    {
        //        FileInfo f = new FileInfo(ofd.FileName); //创建FileInfo对象
        //        ClearUpdateBinFileDisplay();
        //        textBox2.Text = ofd.FileName;
        //        textBox3.Text = f.Length.ToString()+ " Byte";
        //        _loadUpdateFileStatus = true;

        //        Main_updatePath = ofd.FileName;
        //    }
        //    else
        //    {
        //        AddUpdateBinFileDisplay("添加BIN文件出错");
        //        _loadUpdateFileStatus = false;
        //    }
        //}

        //private void Button5_OpenUpdateFile_Click(object sender, EventArgs e)
        //{
        //    //创建打开文件对话框对象
        //    OpenFileDialog ofd = new OpenFileDialog();
        //    ofd.Filter = "|*.bin"; //只查看bin格式文件
        //    if (ofd.ShowDialog() == DialogResult.OK)//判断是选中文件
        //    {
        //        FileInfo f = new FileInfo(ofd.FileName); //创建FileInfo对象
        //        ClearUpdateBinFileDisplay();
        //        textBox5.Text = ofd.FileName;
        //        textBox4.Text = f.Length.ToString() + " Byte";
        //        _loadUpdateFileStatus = true;

        //        Panel_updatePath = ofd.FileName;
        //    }
        //    else
        //    {
        //        AddUpdateBinFileDisplay("添加BIN文件出错");
        //        _loadUpdateFileStatus = false;
        //    }
        //}
        #endregion

        #region 调试辅助信息显示
        //文件信息显示窗口清空显示
        private void ClearUpdateBinFileDisplay()
        {
            this.Invoke(new Action(() =>
            {
                richTextBox2.Text = "";
            }));
        }

        //文件信息显示窗口添加内容显示
        private void AddUpdateBinFileDisplay(string info)
        {
            this.Invoke(new Action(() =>
            {
                richTextBox2.AppendText(info);
            }));
        }

        private void ProcessInfoClear()
        {
            this.Invoke(new Action(() =>
            {
                richTextBox2.Clear();
            }));
        }

        private void ProcessInfoAdd(string text)
        {
            this.Invoke(new Action(() =>
            {
                richTextBox2.Text += text + "\r\n";
            }));
        }
        #endregion

        #region 下载线程处理
        private Thread _fileDownloadThread;
        private SerialPort serialPort = new SerialPort();
        private Ymodem ymodem = new Ymodem();
        private YModemType _yModemType = YModemType.YModem;

        //传输模式选择
        private void customCombox_TransmitMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = comboBox5.SelectedIndex;

            if (index != -1) //非空值
            {
                if (index == 0) //Ymodem
                {
                    _yModemType = YModemType.YModem;
                }
                else if (index == 1) //Ymodem-1K
                {
                    _yModemType = YModemType.YModem_1K;
                }
            }
        }

        //停止文件下载
        private void FileDownloadStop()
        {
            try
            {
                serialPort.Close();
            }
            catch
            {
            }
        }

        //文件下载处理
        private bool FileDownloadProc()
        {
            int baud = 0;
            string portText = "";

            //清空信息
            ProcessInfoClear();
            this.Invoke(new Action(() =>
            {
                this.progressBar1.Value = 0;
                this.label1.Text = "0 %";
            }));

            //串口占用检测
            try
            {
                this.Invoke(new Action(() =>
                {
                    baud = Convert.ToInt32(comboBox4.SelectedItem.ToString());
                    portText = comboBox6.Text;
                }));
                serialPort.PortName = GetSerialPortName(portText);
                serialPort.BaudRate = baud;
                serialPort.Open();

                Debugging.output("uart name=" + serialPort.PortName);
            }
            catch
            {
                ProcessInfoAdd("打开设备的串口失败！");
                this.Invoke(new Action(() =>
                {
                    this.button2.Text = "开始下载";
                    //this.skinButton_FileDownload_StartDownload.BackgroundImage = ymodem_tool.Properties.Resources.Light_blue_button_64px;
                }));
                return false;
            }
            serialPort.Close();

            //开始下载
            ProcessInfoAdd("开始下载...");
            ymodem = new Ymodem();
            ymodem.path = txtSaveBinFilePath.Text;
            ymodem.portName = GetSerialPortName(portText);
            ymodem.baudRate = baud;
            ymodem.NowDownloadProgressEvent += new EventHandler(NowDownloadProgressEvent);
            ymodem.DownloadResultEvent += new EventHandler(DownloadFinishEvent);
            ymodem.YmodemUploadFile(_yModemType, 0);

            return true;
        }

        //下载线程
        private void FileDownloadThreadProc()
        {
            //中途停止下载
            if (_fileDownloadThread != null && _fileDownloadThread.IsAlive)
            {
                ymodem.YmodemUploadFileStop();
                return;
            }

            //开始下载
            this.button2.Text = "取消下载";
            //this.skinButton_FileDownload_StartDownload.BackgroundImage = ymodem_tool.Properties.Resources.Red_button_64px;
            _fileDownloadThread = new Thread(() =>
            {
                FileDownloadProc();
            });
            _fileDownloadThread.IsBackground = true; //设置为后台进程,关闭当前窗体或线程运行结束就会结束该线程
            _fileDownloadThread.Start();
        }

        //开始下载升级
        private void skinButton_FileDownload_StartDownload_Click(object sender, EventArgs e)
        {
            //确认升级文件加载合法性
            if (_loadUpdateFileStatus == false)
            {
                MessageBox.Show("请先加载升级文件！");
                return;
            }

            //下载流程
            FileDownloadThreadProc();
        }
        #endregion

        #region 下载进度委托及事件响应
        private void NowDownloadProgressEvent(object sender, EventArgs e)
        {
            int value = Convert.ToInt32(sender);
            this.Invoke(new Action(() =>
            {
                this.progressBar1.Value = value;
                this.label1.Text = value.ToString() + " %";
            }));
        }
        #endregion

        #region 下载完成委托及事件响应
        private delegate void DownloadFinish(bool finish);

        private void DownloadFinishEvent(object sender, EventArgs e)
        {
            bool finish = (Boolean)sender;
            DownloadFinish status = new DownloadFinish(UploadFileResult);
            this.Invoke(status, finish);
        }

        private void UploadFileResult(bool result)
        {
            if (result == true)
            {
                ProcessInfoAdd("下载成功！");
            }
            else
            {
                ProcessInfoAdd("下载失败！");
            }
            this.button2.Text = "开始下载";
            //this.skinButton_FileDownload_StartDownload.BackgroundImage = ymodem_tool.Properties.Resources.Light_blue_button_64px;
        }

        #endregion

        private void timer1_Tick(object sender, EventArgs e)
        {
            this.toolStripStatusLabel1.Text = "您好,欢迎登录！" + "当前时间：" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
        }

        #region 条码扫描
        protected string ChTable = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        private Byte[] DataList = new Byte[14];
        private Byte[] Data;

        private void BarCodeStrToDate()
        {
            string BarcodeOrgStr = textBox1.Text;
            string BarcodeStr = "";

            for (int i = 0; i < textBox1.Text.Length; i++)
            {
                if (i == 2 | i == 3 | i == 4)
                {
                    for (int j = 0; j < (ChTable.Length); j++)
                    {
                        if (BarcodeOrgStr[i] == ChTable[j])
                        {
                            if (i == 2)
                                BarcodeStr += Convert.ToDecimal(j + 10).ToString().PadLeft(2);
                            else
                                BarcodeStr += Convert.ToDecimal(j).ToString().PadLeft(2);
                        }
                    }
                }
                else
                {
                    BarcodeStr += BarcodeOrgStr[i];
                }
            }
            Data = BitConverter.GetBytes(Convert.ToUInt16(BarcodeStr.Substring(0,  4)));
            Data.CopyTo(DataList, 0);
            Data = BitConverter.GetBytes(Convert.ToUInt16(BarcodeStr.Substring(4,  4)));
            Data.CopyTo(DataList, 2);
            Data = BitConverter.GetBytes(Convert.ToUInt16(BarcodeStr.Substring(8,  3)));
            Data.CopyTo(DataList, 4);
            Data = BitConverter.GetBytes(Convert.ToUInt16(BarcodeStr.Substring(11, 3)));
            Data.CopyTo(DataList, 6);
            Data = BitConverter.GetBytes(Convert.ToUInt16(BarcodeStr.Substring(14, 4)));
            Data.CopyTo(DataList, 8);
            Data = BitConverter.GetBytes(Convert.ToUInt16(BarcodeStr.Substring(18, 4)));
            Data.CopyTo(DataList, 10);
            Data = BitConverter.GetBytes(Convert.ToUInt16(BarcodeStr.Substring(22, 4)));
            Data.CopyTo(DataList, 12);
        }

        private void SendBarCodeStartUpdate()
        {
            byte[] packet = System.Text.Encoding.Default.GetBytes("2");
            serialPort.Write(packet, 0, packet.Length);
        }
        void BarCode_BarCodeEvent(object sender, BarCodesEventArgs barCode)
        {
            ShowInfo(sender, barCode);
            _BarCodeStatus = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Interval = 1000;
            timer1.Start();
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 1)//也可以判断tabControl1.SelectedTab.Text的值
            {
                //执行相应的操作
                BarCode.Start();
                this.textBox1.Clear();
                this.textBox1.Focus();
            }
            else
            {
                _BarCodeStatus = false;
                BarCode.Stop();
            }
        }

        private DateTime _dt = DateTime.Now;  //定义一个成员函数用于保存每次的时间点

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            DateTime tempDt = DateTime.Now;         //保存按键按下时刻的时间点
            TimeSpan ts = tempDt.Subtract(_dt);     //获取时间间隔
            if (ts.Milliseconds > 50)               //判断时间间隔，如果时间间隔大于50毫秒，则将TextBox清空
                this.textBox1.Text = "";
            _dt = tempDt;
        }
        #endregion

        #region 条码烧录线程处理
        private Thread _BarCodeDownloadThread;

        //停止文件下载
        private void BarCodeDownloadStop()
        {
            try
            {
                serialPort.Close();
            }
            catch
            {
            }
        }

        //文件下载处理
        private bool BarCodeDownloadProc()
        {
            int baud = 0;
            string portText = "";
            const byte ACK = 0x06;  /* acknowledge - 接收正确应答命令 */
            const byte C   = 0x43;    /* capital letter C */
            bool transmission_ret = false;
            //清空信息
            richTextBox3.Clear();

            //串口占用检测
            try
            {
                baud = Convert.ToInt32(comboBox4.SelectedItem.ToString());
                portText = comboBox6.Text;
                serialPort.PortName = GetSerialPortName(portText);
                serialPort.BaudRate = baud;
                serialPort.ReadTimeout = 3000;
                serialPort.Open();

                Debugging.output("uart name=" + serialPort.PortName);
            }
            catch
            {
                this.button3.Text = "开始下载";
                this.richTextBox3.Text += "打开设备的串口失败！";
                return false;
            }

            //开始下载
            this.button3.Text = "取消下载";
            this.richTextBox3.Text += "开始下载...\r\n";

            byte[] packet = System.Text.Encoding.Default.GetBytes("2");
            serialPort.Write(packet, 0, packet.Length);

            //等待结束包回复
            if (SerialPortWaitReadEx(C) != true)
            {
                Debugging.output("Wait EOT Packet Ack Overtime!");
                goto end;
            }

            BarCodeStrToDate();
            packet = System.Text.Encoding.Default.GetBytes("3" + textBox1.Text);
            byte[] packet1 = packet.Concat(DataList).ToArray();
            serialPort.Write(packet1, 0, packet1.Length);
            //等待结束包回复
            if (SerialPortWaitReadEx(ACK) != true)
            {
                Debugging.output("Wait EOT Packet Ack Overtime!");
                goto end;
            }

            transmission_ret = true;

        end:
            this.button3.Text = "开始下载";
            if(transmission_ret == true)
            {
                Debugging.output("File Transmission Succesfully!");
                this.richTextBox3.Text += "下载成功！";
            }
            else
            {
                Debugging.output("File Transmission Fail!");
                this.richTextBox3.Text += "下载失败！";
            }

            try
            {
                serialPort.Close();
            }
            catch { }

            return true;
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static long GetMsTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalMilliseconds);
        }

        private bool SerialPortWaitReadEx(byte data)
        {
            long end_msec = GetMsTimeStamp() + serialPort.ReadTimeout; //超时时间的毫秒数
            long start_msec = GetMsTimeStamp(); //当前时间的毫秒数

            while (start_msec <= end_msec)
            {
                try
                {
                    if (serialPort.ReadByte() == data) return true;
                }
                catch { }

                //更新当前时间
                start_msec = GetMsTimeStamp();
            }

            return false;
        }

        //下载线程
        private void BarCodeDownloadThreadProc()
        {
            //开始下载
            this.button3.Text = "取消下载";

            BarCodeDownloadProc();
        }

        //开始下载升级
        private void BarCodeDownload_StartDownload_Click(object sender, EventArgs e)
        {
            //确认升级文件加载合法性
            if (_BarCodeStatus == false)
            {
                MessageBox.Show("请先扫描条码！");
                return;
            }

            //下载流程
            BarCodeDownloadThreadProc();
        }
        #endregion
    }
}
